
import { _decorator, Component, Node, Vec3, v3, director, EventKeyboard } from 'cc';
import yyComponent from '../../Script/Common/yyComponent';
import MapData from '../../Script/GameSpecial/MapData';
import GameConfig from '../../Script/GameSpecial/GameConfig';
import { EventType } from '../../Script/GameSpecial/GameEventType';
import GlobalData from '../../Script/Common/GlobalData';
import { GlobalEnum } from '../../Script/GameSpecial/GlobalEnum';
const { ccclass, property } = _decorator;

/**按Z轴坐标偏移渲染的物体基类 */
@ccclass('TransformItem')
export class TransformItem extends yyComponent {

    protected initSub() {
        this.initMoveState();
    }
    protected resetSub() {
        this.resetMoveState();
    }
    protected registAllCustomUpdate() {
        this.registCustomUpdate(state.jumpUp, this.stepMoveUp);
        this.registCustomUpdate(state.movingNormal, this.stepMoveNormal);
        this.registCustomUpdate(state.movingOut, this.stepMovingOut);
        this.registCustomUpdate(state.movingDown, this.stepMoveDown);
    }
    protected setData(data: { p: Vec3, s: Vec3, eulerAngles: Vec3 }) {
        this.node.setPosition(data.p);
        this.cachePos.set(data.p);
        this.moveSpeed.set(data.s);
        let tr = MapData.getTransform(data.p.z);
        this.preEulerAngles.set(tr.eulerAngles);
        //角速度随机
        this.rotateSpeed.x = (Math.random() - 0.5) * 720;
        this.rotateSpeed.y = (Math.random() - 0.5) * 360;
        this.rotateSpeed.z = (Math.random() - 0.5) * 360;
        if (undefined !== data.eulerAngles) {
            this.node.eulerAngles = data.eulerAngles;
        } else {
            this.node.eulerAngles = v3();
        }
        this.cacheAngle.set(this.node.eulerAngles);
        this.enterCustomUpdateState(state.jumpUp);
    }

    /************************************************************管理属性************************************************************/
    //#region 移动状态
    /**物体原始速度 */
    protected moveSpeed: Vec3;
    /**物体按路径Z坐标偏移后的速度 */
    protected trMoveSpeed: Vec3;
    protected preEulerAngles: Vec3;
    /**缓存物体坐标 */
    protected cachePos: Vec3;
    protected rotateSpeed: Vec3;
    protected cacheAngle: Vec3;
    protected speedChangeCount: number = 0;
    protected maxChangeCount: number = 5;
    protected changeSpeedTime: number = 0;
    protected initMoveState() {
        this.moveSpeed = v3();
        this.trMoveSpeed = v3();
        this.preEulerAngles = v3();
        this.cachePos = v3();
        this.rotateSpeed = v3();
        this.cacheAngle = v3();
        this.speedChangeCount = 0;
        this.changeSpeedTime = 0;
    }
    protected resetMoveState() {
        this.speedChangeCount = 0;
        this.changeSpeedTime = 0;
    }
    //#endregion

    //#region 尺寸
    @property
    protected minVert: Vec3 = v3();
    @property
    protected maxVert: Vec3 = v3();
    //#endregion

    /************************************************************运行状态************************************************************/

    protected updatePos(dt: number) {
        this.computeSpeed(dt);
        this.cachePos.add(this.trMoveSpeed.multiplyScalar(dt));
        this.node.setPosition(this.cachePos);
    }
    protected updateAngle(dt: number) {
        this.cacheAngle.x += this.rotateSpeed.x * dt;
        this.cacheAngle.y += this.rotateSpeed.y * dt;
        this.cacheAngle.z += this.rotateSpeed.z * dt;
        this.node.eulerAngles = this.cacheAngle;
    }

    protected stepMoveUp(dt: number) {
        this.updatePos(dt);
        if (this.checkCull()) {
            return;
        }
        this.updateAngle(dt);
        if (this.checkOutRoad()) {
            this.enterCustomUpdateState(state.movingOut);
        } else if (this.moveSpeed.y < 0) {
            this.enterCustomUpdateState(state.movingNormal)
        }
    }
    protected stepMoveNormal(dt: number) {
        this.updatePos(dt);
        if (this.checkCull()) {
            return;
        }
        this.updateAngle(dt);
        if (this.checkOutRoad()) {
            this.enterCustomUpdateState(state.movingOut);
        } else if (this.checkCollRoad()) {
            this.changeSpeed();
        }
    }

    protected checkCull() {
        let z = GlobalData.get(GlobalEnum.myGlobalDataType.player).node.position.z;
        if (this.cachePos.z - 10 > z) {
            this.emit(EventType.LevelEvent.removeBarrier, this);
            return true;
        }
        return false;
    }

    //撞到轨道，改变速度方向
    protected changeSpeed() {
        if (this.speedChangeCount++ >= this.maxChangeCount) {
            this.enterCustomUpdateState(state.movingDown);
            return;
        }
        let t = director.getCurrentTime();
        if (t - this.changeSpeedTime < 200) {
            return;
        }
        this.changeSpeedTime = t;
        // this.moveSpeed.x = -this.cachePos.x * 5;
        // this.moveSpeed.y = -this.cachePos.y * 3;
        // this.moveSpeed.x *= 0.9;
        if (this.cachePos.x * this.moveSpeed.x > 0) {
            this.moveSpeed.x *= -0.9;
        }
        let minX = 15;
        if (this.moveSpeed.x < minX && this.moveSpeed.x > -minX) {
            if (this.moveSpeed.x < 0) {
                this.moveSpeed.x = -minX;
            } else {
                this.moveSpeed.x = minX;
            }
        }
        this.moveSpeed.y *= -0.8;
        this.moveSpeed.z *= 0.8;
        // this.rotateSpeed.multiplyScalar(0.5);
        this.rotateSpeed.x = (Math.random() - 0.5) * 720;
        this.rotateSpeed.y = (Math.random() - 0.5) * 360;
        this.rotateSpeed.z = (Math.random() - 0.5) * 360;
    }
    protected checkCollRoad() {
        let y = this.cachePos.y;
        if (y > -8.8) {
            return false;
        }
        let x = this.cachePos.x;
        let w = GameConfig.GameRule.roadHalfWidth - this.maxVert.x;
        let d = x * x + y * y;
        if (d < w * w) {
            return false;
        }
        if (x > 12 || x < -12) {
            return false;
        }
        d = Math.sqrt(d);
        this.cachePos.x *= w / d;
        this.cachePos.y *= w / d;
        this.node.setPosition(this.cachePos);
        return true;
    }
    protected checkOutRoad() {
        let x = this.cachePos.x;
        let w = GameConfig.GameRule.roadHalfWidth;
        return this.cachePos.y < -8.8 && (x < -w || x > w);
    }
    protected computeSpeed(dt) {
        let z = this.cachePos.z;
        let tr = MapData.getTransform(z);
        //重力加速度
        let g = GameConfig.GameRule.gravity;
        this.moveSpeed.y -= g * dt;
        // this.rotateY(this.trMoveSpeed, this.moveSpeed, (this.preEulerAngles.y - tr.eulerAngles.y) * 0.017453);
        // this.rotateX(this.moveSpeed, this.trMoveSpeed, (this.preEulerAngles.x - tr.eulerAngles.x) * 0.017453);
        this.rotateY(this.trMoveSpeed, this.moveSpeed, tr.sinY, tr.cosY);
        this.rotateX(this.moveSpeed, this.trMoveSpeed, tr.sinX, tr.cosX);
        this.preEulerAngles.set(tr.eulerAngles);
    }
    protected stepMovingOut(dt: number) {
        this.updatePos(dt);
        if (this.checkCull()) {
            return;
        }
        if (this.cachePos.y < GameConfig.GameRule.roadHalfWidth) {
            this.emit(EventType.LevelEvent.removeBarrier, this);
        } else {
            this.updateAngle(dt);
        }
    }

    protected rotateX(out, v, a, b) {
        let y = v.y;
        // let sin = Math.sin(a);
        // let cos = Math.cos(a);
        let sin = a;
        let cos = b;
        out.x = v.x;
        out.y = y * cos - v.z * sin;
        out.z = y * sin + v.z * cos;
    }

    /**绕 Y 轴旋转向量指定弧度 */
    public rotateY(out, v, a, b) {
        let x = v.x;
        // let sin = Math.sin(a);
        // let cos = Math.cos(a);
        let sin = a;
        let cos = b;
        out.x = v.z * sin + x * cos;
        out.y = v.y;
        out.z = v.z * cos - x * sin;
    }

    protected stepMoveDown(dt: number) {
        this.cachePos.y -= dt * 3;
        if (this.cachePos.y + GameConfig.GameRule.roadHalfWidth + this.maxVert.x < 0) {
            this.emit(EventType.LevelEvent.removeBarrier, this);
            return;
        }
        this.node.setPosition(this.cachePos);
    }

}

enum state {
    none,
    //向上移动
    jumpUp,
    //正常移动
    movingNormal,
    //在轨道外面移动
    movingOut,
    //下沉消失
    movingDown,
}
